#!/usr/bin/env python

"""kde2odb - turn the freedesktop.org configuration files into an open database

This expects to be fed a single file name as an argument, and a long
list of file names on standard input. The argument is a
shared-mime-info xml file, containing a series of mime-type elements,
which specify a mime type and a list of patterns for file names to
check to see if they are of that mime type.

The file names on standard input are a series of freedesktop .desktop
files, that describe an application, giving - among other things -
it's name (in various languages), the mime types it can handle, and
how to invoke it.

Absolutelly no error checking is done on these input files.

These two data sources are mined to produce the beginnings of a
database for the open application. There is no indication in these
files of whether an application is an editor, etc - so we punt on it,
and just provide the "open" flag. The "Terminal" entry is used to provide
the X (Terminal=False) and noX (Terminal=True) flags.

What is written to standard output is the text of an open applications
database. The format is

URL ; flags ; extensions ; name ; command line

at least for now."""

import os, sys
from xml.dom.minidom import parse
from ConfigParser import RawConfigParser, Error, NoOptionError, \
     MissingSectionHeaderError

def usage():
    print >>sys.stderr, "Usage:", sys.argv[0], "<xml file>"
    

# Mapping from a mime type to a list of extensions.
mimedict = dict()
def do_mime_types(types):
    """Pull the list of extensions associated with a mime type."""

    for ele in types:
        mimes = [ele.getAttribute('type')] 
        extlist = []
        for glob in ele.getElementsByTagName('glob'):
            pat = glob.getAttribute('pattern')
            if pat.startswith('*.'):
                extlist.append(pat[2:])
        for alias in ele.getElementsByTagName('alias'):
            mimes.append(alias.getAttribute('type'))
        exts = " ".join(extlist)
        for mime in mimes:
            mimedict[mime] = exts
    

def make_application(desktop):
    """Read the provided file name to see if we get an application."""
    
    cp = RawConfigParser()
    cp.read(desktop)
    flags = ['open']
    try:
        if cp.getboolean("Desktop Entry", "Terminal"):
            flags.append("noX")	 # not clear this is correct, but ...
        else:
            flags.append("X")
    except NoOptionError:
        pass

    types = cp.get("Desktop Entry", "MimeType").split(';')
    extensions = [mimedict[type] for type in types if type]

    command = cp.get("Desktop Entry", "Exec")
    checker = command.split('%')
    for part in checker[1:]:
        if part[0] not in 'uUfF':	# The things I'm willing to recognize
            return
    try:
        name = cp.get("Desktop Entry", "Name")
    except NoOptionError:
        name = command.split()[0]

    if extensions:
        print ";", ' '.join(flags), ";", ' '.join(extensions), \
              ";", name, ";", command


def main(args):
    if len(args) != 2:
        usage()
        sys.exit()
    dom = parse(args[1])
    do_mime_types(dom.getElementsByTagName('mime-type'))

    for filename in sys.stdin:
        try:
            make_application(filename[:-1])
        except KeyError, name:	# Missing mime types
            pass
        except Error, name: # Any configparser errors

            pass

if __name__ == '__main__':
    main(sys.argv)
